home *** CD-ROM | disk | FTP | other *** search
-
-
-
- i
-
- THE PC ASSEMBLER HELPER
-
-
- "The PC Assembler Helper" is an object module (ASMHELP.OBJ) which
- is designed as a companion for "The PC Assembler Tutor". It can
- also be used as an aid in the development of assembler programs
- and subprograms. It allows for input to and output from the
- assembler level, as well as displaying the data in all the 8086
- registers. Part 1 will give a discription of all callable
- subroutines and part 2 will explain how to correctly link a
- program to ASMHELP.OBJ.
-
-
- THE SUBROUTINES
-
- There are a number of routines for displaying data and for
- inputting data. They all follow a standard format.
-
- (1) All subroutines which display output on the monitor at
- the current cursor position start with the word "print_". On
- the screen, all hex output is followed by an 'H'. All signed
- output has a + or a -. Unsigned output has no sign. All
- binary output is distinguishable because it is either 8
- digits or 16 digits long. ASCII output is followed by a
- single asterisk '*' under normal conditions. If one or more
- of the ASCII characters cannot be printed (i.e. if it is
- less than 33d or it is 127d or 255d){1} then it will be
- displayed as a two digit hex number instead of a single
- character. A double asterisk '**' is then used to signal the
- presence of a hex number in an ASCII format. The only time
- there might be confusion is if one of the characters is also
- an asterisk.
-
- (2) All subroutines which get input from the keyboard start
- with the word "get_". They all display prompts to tell you
- what kind of input is desired.
-
- (3) One byte input or output is passed through register AL.
- One word (two byte) input or output is passed through
- register AX. Any input or output that is longer than two
- bytes is passed by reference. The offset address of the data
- is put into AX before calling the subroutine.
-
- Each subroutine returns with all 8086 registers (including the
- flags register) unchanged from when the subroutine was called.
- As an example, if "variable3" is the name of a variable (in
- memory) which we want to print as a signed number, the proper way
- to set up for the calls is:
-
-
- ____________________
-
- 1 In this chapter, as in all others, 'd' stands for decimal,
- 'h' for hex.
-
- ______________________
-
- The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
-
-
-
-
- The PC Assembler Tutor ii
- ______________________
-
- ONE BYTE:
- mov al, variable3
- call print_signed_byte
-
- ONE WORD:
- mov ax, variable3
- call print_signed
-
- FOUR BYTES:
- lea ax, variable3
- call print_signed_4byte
-
- EIGHT BYTES:
- lea ax, variable3
- call print_signed_8byte
-
- For a byte or a word we use the data itself, while for data
- larger than a word we pass the data by reference. The same
- applies for getting input. Here are the subroutines:
-
- get_num
- Enters a number 5 digits or less, either signed or unsigned.
- It does no checking to see if the number is too positive or
- too negative. Returns a two byte value in AX.
-
- print_num
- Prints a word value (from AX) in its signed, unsigned, hex,
- ASCII, and binary representation.
-
-
- All the other input routines do strict error checking. If an
- illegal character is entered or if the input is out of range, the
- subroutine will ask for new input until it receives valid input.
-
-
-
- get_string
- Enters a string of 79 characters or less, and puts a 00h at
- the end of the string (a C string with a maximum total
- length of 80 bytes). The address of the string must be in AX
- before making the call.
-
- print_string
- Displays a 00h terminated string (a C string) on the
- monitor. The address of the first byte of the string must be
- in AX before making the call.
-
-
-
- get_ascii_byte
- Enters a single ascii character and returns it in AL.
-
- print_ascii_byte
- Displays one byte (from AL) as an ascii character.
-
- get_ascii
- Enters one or two characters and returns it (them) in AX.
-
-
-
-
- Appendix I - The PC Assembler Helper iii
- ____________________________________
-
-
- print_ascii
- Displays the value in AX as two characters.
-
-
-
- get_bcd
- Enters a one to eighteen digit signed number as a 10 byte
- bcd number. Commas are allowed. The address of the bcd
- variable must be in AX before calling the routine.
-
- print_bcd
- Displays a 10 byte bcd number as a one to eighteen digit
- signed number with commas. The address of the bcd number
- must be in AX before calling the subroutine.
-
-
-
- get_binary_byte
- Enters a one to eight digit binary number and returns it in
- AL.
-
- print_binary_byte
- Displays a one byte number (from AL) as an eight digit
- binary number.
-
- get_binary
- Enters a one to sixteen digit binary number and returns it
- in AX.
-
- print_binary
- Displays a one word number (from AX) as a sixteen digit
- binary number.
-
-
-
- get_hex_byte
- Enters a one or two digit hex number and returns it in AL.
-
- print_hex_byte
- Displays a one byte number (in AL) as two hex digits.
-
- get_hex
- Enters a one to four digit hex number and returns it in AX.
-
- print_hex
- Displays a one word number (from AX) as a four digit hex
- number.
-
-
-
- get_signed_byte
- Enters a one byte signed number (-128 to +127) and returns
- it in AL.
-
- print signed_byte
- Displays a one byte number (from AL) as a signed number
-
-
-
-
- The PC Assembler Tutor iv
- ______________________
-
- (-128 to +127).
-
- get_signed
- Enters a one word signed number (-32768 to +32767) and
- returns it in AX.
-
- print_signed
- Displays a one word number (from AX) as a signed number
- (-32768 to +32767).
-
- get_signed_4byte
- Enters a 4 byte signed number (-2,147,483,648 to
- +2,147,483,647). Commas are allowed. The address of the 4
- byte number must be in AX before calling the subroutine.
-
- print_signed_4byte
- Displays a 4 byte signed number (-2,147,483,648 to
- +2,147,483,647) with commas. The address of the 4 byte
- number must be in AX before calling the subroutine.
-
- get_signed_8byte
- Enters an 8 byte signed number (-9,223,372,036,854,775,808
- to +9,223,372,036,854,775,807). Commas are allowed. The
- address of the 8 byte number must be in AX before calling
- the subroutine. The screen prompt will show the last 3
- negative digits as -807 instead of -808, but this is because
- of lack of screen space.
-
- print_signed_8byte
- Displays an 8 byte signed number (-9,223,372,036,854,775,808
- to +9,223,372,036,854,775,807) with commas. The address of
- the 8 byte number must be in AX before calling the
- subroutine.
-
-
-
- get_unsigned_byte
- Enters a one byte unsigned number (0 to 255) and returns it
- in AL.
-
- print_unsigned_byte
- Displays a one byte number (from AL) as an unsigned number
- (0 to 255).
-
- get_unsigned
- Enters a one word unsigned number (0 to 65535) and returns
- it in AX.
-
- print_unsigned
- Displays a one word number (from AX) as an unsigned number
- (0 to 65535).
-
- get_unsigned_4byte
- Enters a 4 byte unsigned number (0 to 4,294,967,295). Commas
- are allowed. The address of the 4 byte number must be in AX
- before calling the subroutine.
-
-
-
-
-
- Appendix I - The PC Assembler Helper v
- ____________________________________
-
- print_unsigned_4byte
- Displays a 4 byte unsigned number (0 to 4,294,967,295) with
- commas. The address of the 4 byte number must be in AX
- before calling the subroutine.
-
- get_unsigned_8byte
- Enters an 8 byte unsigned number (0 to
- 18,446,744,073,709,551,615). Commas are allowed. The address
- of the 8 byte number must be in AX before calling the
- subroutine.
-
- print_unsigned_8byte
- Displays an 8 byte unsigned number (0 to
- 18,446,744,073,709,551,615) with commas. The address of the
- 8 byte number must be in AX before calling the subroutine.
-
-
- Some of the above routines allow commas to be used for data
- entry. These routines strip the commas before looking at the
- number, so the following numbers all give the equivalent input:
-
- 2134875
- 2,134,875
- 21,,,34875
- 2,1,3,4,8,7,5
- 21,34,87,5
-
- show_regs
- Displays the 8086 registers on the top of the screen. Each
- call to show_regs increments a resettable counter so you can
- know where you are in the program. The counter starts with
- an initial value of 0. It also scrolls the screen up if the
- cursor is past line 19.
-
- show_regs_and_wait
- The same as show_regs except that it waits for you to press
- ENTER before continuing.
-
- set_count
- Sets the counter in show_regs to the value in AX. The new
- counter value (incremented by 1) will appear the next time
- show_regs is called.
-
- set_blue
- If you have a color monitor which is displaying color text,
- it sets the background to blue.
-
- get_continue
- Waits for you to press ENTER before continuing the program.
- It enters no data. See also set_timer below.
-
- set_timer
- In order to allow use with a debugger, it is possible to set
- a timer so the print functions keep control of the screen
- for a specific amount of time. To use set_timer, you put a
- number from 1 to 5 in AL, and call set_timer. This will
- cause a 1 to 5 second delay every time a print function or
-
-
-
-
- The PC Assembler Tutor vi
- ______________________
-
- show_regs is called. A 0 in AL will reset the timer to 0. A
- number larger than 5 in AL will cause ASMHELP to wait for
- you to press the ENTER key every time a print function or
- show_regs is called.
-
- kill_timer
- Resets the timer to 0.
-
- set_reg_style
- Sets the display style of the individual registers. The
- correct order of the definition is:
-
- AX, BX, CX, DX, SI, DI, BP, SP
-
- The style values are:
-
- FULL REGISTER OR RIGHT HALF REGISTER
-
- signed = 1d 1h
- unsigned = 2d 2h
- binary = 3d 3h
- hex = 4d 4h
- ascii = 5d 5h
-
- plus (if applicable)
-
- LEFT HALF REGISTER AND HALF REG. BIT
-
- signed = 144d 90h
- unsigned = 160d A0h
- binary = 176d B0h
- hex = 192d C0h
- ascii = 208d D0h
-
-
- set_reg_style makes a COPY of the information, which is used
- the next (and subsequent) times that show_regs is called.
- The next several paragraphs explain how this works. AX must
- contain the address of the 8 byte style definition array
- before calling set_reg_style.
-
-
- REGISTER DISPLAY STYLE
-
- The 8086 contains a number of different registers. Some of these
- always contain addresses and are always displayed in hex. These
- are CS, DS, ES, SS and IP. They are always in hex and cannot be
- changed. Also, each flag has an unchangeable style which will be
- explained later.
-
- This still leaves us with AX, BX, CX, DX, SI, DI, BP and SP. Any
- of these registers can be displayed in any style desired. In
- addition, AX, BX, CX and DX can each be broken into two half
- registers, and each half register has an independent style. The
- default style is full register, unsigned. If you call show_regs
- without setting a style, the eight abovementioned registers will
- all display full, unsigned numbers.
-
-
-
-
- Appendix I - The PC Assembler Helper vii
- ____________________________________
-
-
- In order to change the style, you need to set up an 8 byte style
- definition array in your data segment. The correct definition for
- this is the following:
-
- ax_byte db 2
- bx_byte db 2
- cx_byte db 2
- dx_byte db 2
- si_byte db 2
- di_byte db 2
- bp_byte db 2
- sp_byte db 2
-
- This is the order that ASMHELP.OBJ expects. It is also the order
- that the registers appear on the screen. The number 2 is the
- default value for each byte. Once you have defined the 8 bytes,
- you may alter any of them that you want to.
-
- The possible styles are signed, unsigned, binary, hex, and ascii.
- If you look at a byte:
-
- 76543210
- HLLL0RRR
-
- the leftmost bit (80h or 128d) signals a half or a full register.
- If it is 1, you get a half register, if it is 0, you get a full
- register. bits 4,5 and 6 represent the left half register (if
- appropriate), while bits 0,1 and 2 represent either the full
- register or the right half register. For SI, DI, BP and SP, only
- bits 0, 1 and 2 are significant. For AX, BX, CX and DX, all bits
- except bit 3 are significant.
-
- The code for bits 0, 1 and 2 is the following:
-
- signed = 1d 1h
- unsigned = 2d 2h
- binary = 3d 3h
- hex = 4d 4h
- ascii = 5d 5h
-
- This is the correct code for either a full register or the right
- half register.
-
- If you want half registers, you must add 80h (128d) and the code
- for the left half register. We have for the left half register:
-
- DECIMAL HEX
-
- signed = 16d + 128d 10h + 80h
- unsigned = 32d + 128d 20h + 80h
- binary = 48d + 128d 30h + 80h
- hex = 64d + 128d 40h + 80h
- ascii = 80d + 128d 50h + 80h
-
- which is the same as the above codes but shifted left 4 bits.
- Since the 128d and the left half register code always appear in
-
-
-
-
- The PC Assembler Tutor viii
- ______________________
-
- tandem, we may simply add them together. This gives us:
-
- DECIMAL HEX
-
- signed = 144d 90h
- unsigned = 160d A0h
- binary = 176d B0h
- hex = 192d C0h
- ascii = 208d D0h
-
- Here are some examples:
-
- signed left + hex right = 144 + 4 = 148
- ascii left + unsigned right = 208 + 2 = 210
- binary left + ascii right = 176 + 5 = 181
-
- Simply move the constant to the appropriate byte:
-
- mov cx_byte, 210 ; ascii left, unsigned right
- mov ax_byte, 5 ; full register, ascii
- mov si_byte, 1 ; full register signed
- mov dx_byte, 148 ; signed left, hex right
- mov bx_byte, 4 ; full register, hex
-
- After you have changed all the styles you want to, put the
- address of ax_byte (the first byte of the array) in ax and call
- set_reg_style:
-
- lea ax, ax_byte
- call set_reg_style
-
- ASMHELP.OBJ uses the address in AX and stores a COPY of those 8
- bytes. The next time you call show_regs, it will use this copy to
- define the styles. If you make a mistake, it will default to
- unsigned.
-
- Registers are displayed the same way as with the 'print_'
- subroutines. Unsigned numbers have no sign. Signed numbers have a
- + or -, hex has an 'H', binary is either 8 or 16 digits, and
- ascii has a single asterisk '*' unless one of the characters is
- not printable ( 00d to 32d, 127d and 255d) in which case the non-
- printable character will be written as a two digit hex number,
- and a double asterisk will signal the event.
-
-
-
- Finally, the flags are displayed as follows:
-
- OF, IEF, TF, ZF, AF, and CF are blank if they are not set and
- have an X if they are set.
-
- DF has a + or a - to indicate increment or decrement.
-
- SF has a + or a - to indicate the sign.
-
- PF has E (for even) or O (for odd).
-
-
-
-
-
- Appendix I - The PC Assembler Helper ix
- ____________________________________
-
-
-
- LINKING
-
- In order to use ASMHELP.OBJ you must have some standard segments
- in your program. The standard code segment is defined as:
-
- CODESTUFF SEGMENT PUBLIC 'CODE'
-
- and the standard data segment is:
-
- DATASTUFF SEGMENT PUBLIC 'DATA'
-
- In addition you need a stack segment:
-
- STACKSEG SEGMENT STACK 'STACK'
-
- which should have at least 100 bytes for ASMHELP to use.
-
- ASMHELP.OBJ expects that when you call one of its routines the
- following conditions are met:
-
- (1) It is a near call, and CS is set to the CODESTUFF
- segment.
-
- (2) DS is set to the DATASTUFF segment. Any data which is
- longer than one word long and is being transferred must be
- in the DATASTUFF segment and its offset address must be in
- AX. For one byte or one word data, the data itself is in
- AX/AL.
-
- (3) There is available stack space.
-
- In order to link properly, any subroutine which is called must
- have an EXTRN statement.
-
- EXTRN show_regs:NEAR
-
- If the above conditions hold, then simply link your object file
- with asmhelp.obj:
-
- C> link myfile.obj+asmhelp.obj
-
- and the subroutines will be usable.
-
-
-
- ALIASES
-
- The subroutine names were chosen so their functions would be
- completely clear. However, they tend to be long so if you use
- them with some frequency it would be easier to use aliases. Make
- a redefinition macro file and then include it at the beginning of
- the program. For instance, if you have:
-
- call print_unsigned_8byte
-
-
-
-
-
- The PC Assembler Tutor x
- ______________________
-
- you might want the EQU statement
-
- prt_u8 EQU print_unsigned_8byte
-
- and then rewrite the call:
-
- call prt_u8
-
- Include redefinitions which are reasonable to you and put them in
- a file REDEF.MAC.
-
- prt_s8 EQU print_signed_8byte
- get_u4 EQU get_unsigned_4byte
- show_rw EQU show_regs_and_wait
-
- Then all you need on the first line of your program is:
-
- include REDEF.MAC
-
- and the assembler will do the work for you.
-
-
-
- MEMORY RESIDENT SHOW_REGS
-
- If you are not using a debugger, it is possible to have the
- show_regs portion of The Assembler Helper resident in memory.
- This means that once it is installed, it will stay there till you
- turn the machine off or reset the machine. The name of the
- program is HELPMEM.COM and it is in \XTRAFILE. It operates
- exactly the same way as show_regs except you get to it by using
- INT 3. At that point you can set TF to do single stepping.
-
- You load it into memory by typing:
-
- >helpmem
-
- and it will wait for you to send interrupts.
-
- The first time you do INT 3, you will see the normal show_regs
- screen. The count is reset to 0 each time you have an INT 3.
- There will also be two menu lines:
-
- ----------
- 0=clear TF ; X=set TF ; A=regs from ax ; B=set count ; C=continue
- 1=ax ; 2=bx ; 3=cx ; 4=dx ; 5=si ; 6=di ; 7=bp ; 8=sp
- ----------
-
- This is pretty clear. 0 clears TF and X sets TF. If you press B
- you will be prompted for a new count number. C lets you continue.
- You can set the registers individually. Each register has a
- number; ax is 1, bx is 2, etc. When you press the number, you
- will be prompted for a HEX style code. This is the same style
- code you have been using all the time.
-
- Finally, if you want to transfer the style information from your
- program, do the following:
-
-
-
-
- Appendix I - The PC Assembler Helper xi
- ____________________________________
-
-
- mov ax, offset ax_byte
- int 3
-
- Load the address of ax_byte in AX before the interrupt, and then
- press selection A. The 8 bytes located at the address in AX will
- be transfered to HELPMEM. The advantage of this is that you can
- run ASMHELP concurrently, and they will both show the same
- register styles.
-
-
- When you move into single step mode, you get a different prompt
- line:
-
- ----------
- 0 = clear TF and continue ; 2 = menu ; other keys = continue
- ----------
-
- 0 clears TF, 2 sends you to the above menu, and any other key
- will continue the program with TF set.
-
-
- As is true with all debuggers, you should not single step through
- subroutine calls since the subroutine might have hundreds or
- thousands of steps. In addition, the subroutines in ASMHELP store
- the flags. This means that they may store the flags with the trap
- flag set. If you clear the trap flag while inside ASMHELP, when
- the code exits ASMHELP it will POP the flags with the trap flag
- set. If this happens, keep pressing 0 until you get out of single
- step mode.
-
- The memory resident version works fine for single stepping as
- long as there are no interrupts or subroutine calls. The
- show_regs in ASMHELP works fine inbetween subroutine calls but
- requires a lot of coding for single stepping. Therefore, a
- strategy for using these two programs in conjunction is:
-
- 1) use the same register style definition array for both
- programs.
-
- 2) when there is only 8086 code with no interrupts or
- subroutine calls, use INT 3 and single step.
-
- 3) When there are interrupts and subroutines interspersed
- with the 8086 instructions, switch to ASMHELP.
-
- The screens should look the same except the count will be
- different.
-
-
-
- I/O
-
- All data i/o is done to the current screen at the current cursor
- position. As long as you are in a text mode, ASMHELP should write
- to whatever is current.
-
-
-
-
-
- The PC Assembler Tutor xii
- ______________________
-
- SHOW_REGS is a different matter. The only allowed modes are 2, 3
- and 7. If you enter in modes 2, 3 or 7, it will keep the same
- mode. If it is in any other mode, the video card will be forced
- to mode 3.
-
- The memory resident version does almost the same thing. Every
- time it is called, it checks for modes 2, 3 or 7, and if the mode
- is not one of these, changes the mode to mode 3. If the mode is
- 3, then HELPMEM looks at the first character on page 0 and uses
- the attribute of that character for all its display operations.
- Whatever display attribute is in the upper left hand corner of
- page 0 will be the display attribute for everything.
-
- The register display occupies the first 10 lines of page 0 of
- whatever mode you are in. This is written directly to memory and
- cannot be changed. Both versions change the page to page 0 upon
- entry. If you are on another page, after a call to show_regs you
- will be on page 0 at its current cursor position.
-
- If you use ASMHELP in a programming environment or with a
- debugger there may be conflicts as to who controls the screen
- display. HELPMEM.COM should not be used in a programming
- environment and cannot be used with a debugger, since both
- HELPMEM and the debugger try to use the same interrupts.
-
-